from django.contrib import messages
from django.core.paginator import Paginator
from django.shortcuts import render, get_object_or_404, redirect
from django.http import JsonResponse, HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.db.models import Q, Count, Avg
from django.utils import timezone
from django.contrib.auth.decorators import login_required
import json
from django.utils.decorators import method_decorator
from django.views import View
from django.views.decorators.http import require_http_methods, require_POST
from Customer.models import CustomUser, Follow, UserProfile
from django.conf import settings
from .models import Event, EventCategory, EventRegistration, EventReview, EventImage, EventDiscussion, DiscussionLike, \
    PostDraft, PointTransaction, Checkin
from .models import CommunityPost, PostComment, PostLike, CommentLike, UserMessage, UserActivity
from datetime import datetime, timedelta
@login_required
def index(request):
    """首页视图 - 使用数据库数据"""
    try:
        # 获取已发布的活动，按创建时间倒序排列
        published_events = Event.objects.filter(
            status='published',
            start_time__gte=timezone.now()
        ).order_by('-created_at')[:8]

        # 获取热门活动（按浏览数）
        popular_events = Event.objects.filter(
            status='published',
            start_time__gte=timezone.now()
        ).order_by('-views_count')[:4]

        # 为每个活动设置图片URL - 修复这里
        for event in published_events:
            event.image_url = get_primary_image_url(event)
            # 计算平均评分
            avg_rating = event.reviews.aggregate(Avg('rating'))['rating__avg'] or 0
            event.avg_rating = round(avg_rating, 1)

        for event in popular_events:
            event.image_url = get_primary_image_url(event)
            # 计算平均评分
            avg_rating = event.reviews.aggregate(Avg('rating'))['rating__avg'] or 0
            event.avg_rating = round(avg_rating, 1)

        # 获取所有活动分类
        categories = EventCategory.objects.filter(is_active=True)

        context = {
            'page_title': '本地有约 - 发现身边的精彩活动',
            'events': published_events,
            'popular_events': popular_events,
            'categories': categories,
            'user': request.user
        }
        return render(request, 'index.html', context)
    except Exception as e:
        print(f"首页加载错误: {str(e)}")
        context = {
            'page_title': '本地有约 - 发现身边的精彩活动',
            'error_message': '数据加载中，请稍后...'
        }
        return render(request, 'index.html', context)

def get_event_image_url(request, event_id):
    """获取活动图片URL API"""
    try:
        event = get_object_or_404(Event, id=event_id)
        image_url = get_primary_image_url(event)

        return JsonResponse({
            'success': True,
            'image_url': image_url,
            'event_id': event_id
        })
    except Exception as e:
        return JsonResponse({
            'success': False,
            'error': str(e)
        }, status=500)
def get_primary_image(activity):
    """获取活动主图"""
    try:
        primary_image = activity.images.filter(is_primary=True).first()
        if primary_image:
            return primary_image.image.url

        # 如果没有主图，返回第一个图片
        first_image = activity.images.first()
        if first_image:
            return first_image.image.url
    except:
        pass

    # 返回默认图片
    default_images = [
        'https://images.unsplash.com/photo-1546519638-68e109498ffc?ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60',
        'https://images.unsplash.com/photo-1526379879527-8559ecfcaec0?ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60',
        'https://images.unsplash.com/photo-1541961017774-22349e4a1262?ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60'
    ]
    return default_images[activity.id % len(default_images)]
from math import radians, sin, cos, sqrt, atan2
def calculate_distance(user_lat, user_lng, activity_lat, activity_lng):
    """计算两个坐标点之间的距离（公里）"""
    if not all([user_lat, user_lng, activity_lat, activity_lng]):
        return "距离未知"

    try:
        # 将十进制度数转化为弧度
        lat1, lon1, lat2, lon2 = map(radians, [user_lat, user_lng, activity_lat, activity_lng])

        # 哈弗辛公式计算距离
        dlon = lon2 - lon1
        dlat = lat2 - lat1
        a = sin(dlat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(dlon / 2) ** 2
        c = 2 * atan2(sqrt(a), sqrt(1 - a))
        distance_km = 6371 * c  # 地球平均半径，单位公里

        if distance_km < 1:
            return f"{int(distance_km * 1000)}m"  # 小于1公里显示米
        else:
            return f"{distance_km:.1f}km"  # 大于1公里显示公里，保留1位小数
    except:
        return "距离未知"


def format_real_date(start_time):
    """格式化真实日期显示"""
    now = timezone.now()
    time_diff = start_time - now

    # 如果活动已经开始
    if time_diff.total_seconds() < 0:
        days_ago = abs(time_diff.days)
        if days_ago == 0:
            return "今天"
        elif days_ago == 1:
            return "昨天"
        elif days_ago < 7:
            return f"{days_ago}天前"
        else:
            return start_time.strftime('%m月%d日')

    # 活动还未开始
    days_diff = time_diff.days
    hours_diff = int(time_diff.total_seconds() // 3600)

    if days_diff == 0:
        if hours_diff < 1:
            minutes = int(time_diff.total_seconds() // 60)
            return f"{minutes}分钟后" if minutes > 0 else "即将开始"
        elif hours_diff < 24:
            return f"{hours_diff}小时后"
    elif days_diff == 1:
        return "明天"
    elif days_diff < 7:
        return f"{days_diff}天后"
    else:
        return start_time.strftime('%m月%d日 %H:%M')

def activity_list(request):
    """活动列表页面 - 支持筛选、搜索、排序，支持 AJAX 局部刷新"""
    # 获取已发布的活动，预加载相关数据
    # activities_queryset = Event.objects.filter(status='published').prefetch_related('images', 'reviews', 'category')
    activities_queryset = Event.objects.filter(status='published').prefetch_related('images', 'reviews',
                                                                                    'category').order_by('-start_time')
    # 搜索功能
    search_query = request.GET.get('search', '')
    if search_query:
        activities_queryset = activities_queryset.filter(
            Q(title__icontains=search_query) |
            Q(description__icontains=search_query) |
            Q(location__icontains=search_query) |
            Q(category__name__icontains=search_query)
        )

    # 分类筛选
    category_id = request.GET.get('category')
    if category_id:
        activities_queryset = activities_queryset.filter(category_id=category_id)

    # 时间筛选
    time_filter = request.GET.get('time')
    now = timezone.now()
    if time_filter == 'today':
        today_start = now.replace(hour=0, minute=0, second=0, microsecond=0)
        today_end = today_start + timedelta(days=1)
        activities_queryset = activities_queryset.filter(
            start_time__gte=today_start,
            start_time__lt=today_end
        )
    elif time_filter == 'week':
        week_end = now + timedelta(days=7)
        activities_queryset = activities_queryset.filter(
            start_time__gte=now,
            start_time__lte=week_end
        )
    elif time_filter == 'month':
        month_end = now + timedelta(days=30)
        activities_queryset = activities_queryset.filter(
            start_time__gte=now,
            start_time__lte=month_end
        )

    # 获取用户位置信息
    user_lat = request.GET.get('lat')
    user_lng = request.GET.get('lng')

    # 如果有用户位置信息，可以按距离排序
    if user_lat and user_lng:
        try:
            user_lat = float(user_lat)
            user_lng = float(user_lng)

            # 为每个活动计算距离并添加到annotate中
            # 这里简化处理，实际应该使用数据库的空间函数进行距离计算和排序
            pass
        except (ValueError, TypeError):
            user_lat = None
            user_lng = None

    # 排序
    sort_by = request.GET.get('sort', 'start_time')
    if sort_by == 'rating':
        # 按平均评分排序
        activities_queryset = activities_queryset.annotate(
            avg_rating=Avg('reviews__rating')
        ).order_by('-avg_rating')
    elif sort_by == 'popular':
        activities_queryset = activities_queryset.order_by('-current_participants')
    elif sort_by == 'newest':
        activities_queryset = activities_queryset.order_by('-created_at')
    elif sort_by == 'distance' and user_lat and user_lng:
        # 如果有用户位置，可以按距离排序
        # 简化处理：按ID排序，实际应该按距离计算
        activities_queryset = activities_queryset.order_by('id')
    else:  # start_time
        activities_queryset = activities_queryset.order_by('start_time')

    # 分页
    paginator = Paginator(activities_queryset, 6)
    page_number = request.GET.get('page', 1)
    page_obj = paginator.get_page(page_number)

    # 获取所有活动分类
    categories = EventCategory.objects.filter(is_active=True)

    # 检查是否为 AJAX 请求
    if request.headers.get('X-Requested-With') == 'XMLHttpRequest' or request.GET.get('ajax'):
        # 准备活动数据
        activities_data = []
        for activity in page_obj:
            # 获取图片URL
            image_url = get_primary_image_url(activity)

            # 计算平均评分
            avg_rating = activity.reviews.aggregate(Avg('rating'))['rating__avg'] or 0

            # 计算真实距离
            distance = "距离未知"
            if user_lat and user_lng and activity.latitude and activity.longitude:
                try:
                    distance = calculate_distance(
                        float(user_lat), float(user_lng),
                        float(activity.latitude), float(activity.longitude)
                    )
                except:
                    distance = "距离未知"

            # 格式化真实时间
            time_display = format_real_date(activity.start_time)

            # 检查是否有自定义图片
            has_custom_image = activity.images.exists()

            activities_data.append({
                'id': activity.id,
                'title': activity.title,
                'description': activity.description,
                'location': activity.location,
                'start_time': activity.start_time.isoformat(),
                'start_time_display': time_display,  # 添加格式化后的时间显示
                'category': {
                    'id': activity.category.id if activity.category else 0,
                    'name': activity.category.name if activity.category else '未分类',
                    'icon': activity.category.icon if activity.category else '🏷️'
                },
                'organizer': {
                    'id': activity.organizer.id,
                    'username': activity.organizer.username
                },
                'participant_count': activity.current_participants,
                'max_participants': activity.max_participants,
                'rating': round(avg_rating, 1),
                'distance': distance,  # 使用真实距离
                'image_url': image_url,
                'can_register': activity.can_register,
                'latitude': float(activity.latitude) if activity.latitude else None,
                'longitude': float(activity.longitude) if activity.longitude else None,
                'has_custom_image': has_custom_image
            })

        return JsonResponse({
            'activities': activities_data,
            'pagination': {
                'current_page': page_obj.number,
                'total_pages': paginator.num_pages,
                'has_previous': page_obj.has_previous(),
                'has_next': page_obj.has_next(),
                'previous_page_number': page_obj.previous_page_number() if page_obj.has_previous() else None,
                'next_page_number': page_obj.next_page_number() if page_obj.has_next() else None,
            },
            'total_activities': paginator.count
        })
    else:
        # 为非AJAX请求也处理数据
        for activity in page_obj:
            activity.image_url = get_primary_image_url(activity)
            activity.has_custom_image = activity.images.exists()

            # 计算真实距离和时间显示
            if user_lat and user_lng and activity.latitude and activity.longitude:
                try:
                    activity.distance = calculate_distance(
                        float(user_lat), float(user_lng),
                        float(activity.latitude), float(activity.longitude)
                    )
                except:
                    activity.distance = "距离未知"
            else:
                activity.distance = "距离未知"

            activity.time_display = format_real_date(activity.start_time)

        # 返回完整页面
        context = {
            'page_obj': page_obj,
            'activities': page_obj,
            'categories': categories,
            'search_query': search_query,
            'selected_category': category_id,
            'selected_sort': sort_by,
            'selected_time': time_filter,
            'total_activities': paginator.count,
            'user_location': '北京市朝阳区',
        }
        return render(request, 'activities.html', context)

# 添加活动删除函数
@login_required
def delete_event(request, event_id):
    """删除活动及其所有图片"""
    try:
        event = get_object_or_404(Event, id=event_id, organizer=request.user)

        # 删除活动相关的所有图片（会触发模型的delete方法）
        event.images.all().delete()

        # 删除活动
        event.delete()

        return JsonResponse({
            'success': True,
            'message': '活动删除成功'
        })

    except Exception as e:
        return JsonResponse({
            'success': False,
            'message': f'删除活动失败: {str(e)}'
        })

@login_required
def activity_create(request):
    """创建活动视图 - 处理GET和POST请求，支持编辑草稿"""
    categories = EventCategory.objects.filter(is_active=True)

    # 处理草稿编辑
    draft_id = request.GET.get('draft_id')
    draft = None
    if draft_id:
        try:
            draft = Event.objects.get(
                id=draft_id,
                organizer=request.user,
                status='draft'
            )
        except Event.DoesNotExist:
            messages.error(request, '草稿不存在或无权编辑')

    if request.method == 'POST':
        try:
            print("收到创建/编辑活动请求")  # 调试信息

            # 获取表单数据
            title = request.POST.get('title', '').strip()
            category_id = request.POST.get('category')
            start_time = request.POST.get('start_time')
            end_time = request.POST.get('end_time')
            registration_deadline = request.POST.get('registration_deadline')
            location = request.POST.get('location', '').strip()
            latitude = request.POST.get('latitude')
            longitude = request.POST.get('longitude')
            max_participants = request.POST.get('max_participants')
            is_free = request.POST.get('is_free') == 'true'
            fee = request.POST.get('fee', 0) if not is_free else 0
            description = request.POST.get('description', '').strip()
            is_draft = request.POST.get('is_draft') == 'true'  # 草稿标识

            # 检查是创建新活动还是更新草稿
            draft_id = request.POST.get('draft_id')
            is_editing_draft = bool(draft_id)

            print(
                f"表单数据: title={title}, category={category_id}, location={location}, is_draft={is_draft}, is_editing_draft={is_editing_draft}")

            # 验证必要字段
            required_fields = {
                'title': title,
                'category': category_id,
                'start_time': start_time,
                'end_time': end_time,
                'registration_deadline': registration_deadline,
                'location': location,
                'latitude': latitude,
                'longitude': longitude,
                'max_participants': max_participants,
                'description': description
            }

            missing_fields = [field for field, value in required_fields.items() if not value]
            if missing_fields and not is_draft:  # 草稿不需要所有必填字段
                return JsonResponse({
                    'success': False,
                    'message': f'请填写所有必填字段: {", ".join(missing_fields)}'
                })

            # 草稿只需要标题
            if is_draft and not title:
                return JsonResponse({
                    'success': False,
                    'message': '草稿至少需要填写活动标题'
                })

            # 验证分类是否存在
            try:
                category = EventCategory.objects.get(id=category_id)
            except EventCategory.DoesNotExist:
                return JsonResponse({
                    'success': False,
                    'message': '选择的活动分类不存在'
                })

            # 转换时间格式
            try:
                start_time_dt = datetime.fromisoformat(start_time.replace('Z', '+00:00'))
                end_time_dt = datetime.fromisoformat(end_time.replace('Z', '+00:00'))
                registration_deadline_dt = datetime.fromisoformat(registration_deadline.replace('Z', '+00:00'))
            except ValueError as e:
                if not is_draft:  # 草稿可以没有时间
                    return JsonResponse({
                        'success': False,
                        'message': f'时间格式错误: {str(e)}'
                    })
                else:
                    # 草稿使用默认时间
                    from django.utils import timezone
                    start_time_dt = timezone.now() + timedelta(days=1)
                    end_time_dt = timezone.now() + timedelta(days=1, hours=2)
                    registration_deadline_dt = timezone.now() + timedelta(hours=23)

            # 确定活动状态
            if is_draft:
                status = 'draft'  # 草稿状态
                success_message = '活动草稿保存成功！'
            else:
                status = 'pending'  # 待审核状态
                success_message = '活动提交成功，等待管理员审核！'

            # 创建或更新活动对象
            if is_editing_draft and draft_id:
                # 更新现有草稿
                try:
                    event = Event.objects.get(
                        id=draft_id,
                        organizer=request.user,
                        status='draft'
                    )
                    # 更新字段
                    event.title = title
                    event.category = category
                    event.start_time = start_time_dt
                    event.end_time = end_time_dt
                    event.registration_deadline = registration_deadline_dt
                    event.location = location
                    event.latitude = float(latitude) if latitude else 0
                    event.longitude = float(longitude) if longitude else 0
                    event.max_participants = int(max_participants) if max_participants else 10
                    event.is_free = is_free
                    event.fee = float(fee) if fee else 0
                    event.description = description
                    event.status = status
                    event.save()
                    print(f"✅ 草稿更新成功，ID: {event.id}, 状态: {status}")
                except Event.DoesNotExist:
                    return JsonResponse({
                        'success': False,
                        'message': '草稿不存在或无权编辑'
                    })
            else:
                # 创建新活动
                event = Event(
                    title=title,
                    category=category,
                    start_time=start_time_dt,
                    end_time=end_time_dt,
                    registration_deadline=registration_deadline_dt,
                    location=location,
                    latitude=float(latitude) if latitude else 0,
                    longitude=float(longitude) if longitude else 0,
                    max_participants=int(max_participants) if max_participants else 10,
                    current_participants=0,
                    is_free=is_free,
                    fee=float(fee) if fee else 0,
                    description=description,
                    organizer=request.user,
                    status=status,
                    views_count=0
                )
                event.save()
                print(f"✅ 活动创建成功，ID: {event.id}, 状态: {status}")

            # 处理上传的图片
            images = request.FILES.getlist('images')
            print(f"收到 {len(images)} 张图片")

            if images:
                # 删除旧的图片（如果是编辑草稿）
                if is_editing_draft:
                    event.images.all().delete()

                for i, image_file in enumerate(images):
                    # 验证图片大小和类型
                    if image_file.size > 5 * 1024 * 1024:  # 5MB
                        print(f"图片 {image_file.name} 过大，跳过")
                        continue

                    if not image_file.content_type.startswith('image/'):
                        print(f"文件 {image_file.name} 不是图片，跳过")
                        continue

                    try:
                        # 创建图片记录
                        event_image = EventImage(
                            event=event,
                            is_primary=(i == 0),  # 第一个图片设为主图
                            uploaded_by=request.user
                        )
                        event_image.image.save(image_file.name, image_file)
                        event_image.save()
                        print(f"图片保存成功: {event_image.image.name}")
                    except Exception as e:
                        print(f"保存图片 {image_file.name} 时出错: {str(e)}")
                        continue

            # 返回成功响应
            return JsonResponse({
                'success': True,
                'message': success_message,
                'redirect_url': '/customer/profile/',
                'is_draft': is_draft,
                'is_editing': is_editing_draft
            })

        except Exception as e:
            print(f"❌ 创建/编辑活动错误: {str(e)}")
            import traceback
            traceback.print_exc()
            return JsonResponse({
                'success': False,
                'message': f'操作失败: {str(e)}'
            })

    # GET请求 - 显示创建/编辑表单
    context = {
        'categories': categories,
        'draft': draft,  # 传递草稿对象到模板
        'is_editing_draft': bool(draft)  # 标识是否为编辑模式
    }
    return render(request, 'activity_create.html', context)

def get_primary_image_url(event):
    """获取活动主图的URL - 直接从模型获取，OSS会自动处理URL"""
    try:
        # 方法1: 查找主图
        primary_image = EventImage.objects.filter(event=event, is_primary=True).first()
        if primary_image and primary_image.image:
            return primary_image.image.url

        # 方法2: 查找第一个图片
        first_image = EventImage.objects.filter(event=event).first()
        if first_image and first_image.image:
            # 自动设置为主图
            first_image.is_primary = True
            first_image.save()
            return first_image.image.url

    except Exception as e:
        print(f"获取图片URL错误: {str(e)}")

    # 如果没有图片，返回默认图片（使用CDN或本地静态文件）
    return get_default_image_url()

def get_default_image_url():
    """获取默认图片URL - 使用CDN或本地静态文件"""
    default_images = [
        'https://images.unsplash.com/photo-1546519638-68e109498ffc?ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60',
        'https://images.unsplash.com/photo-1526379879527-8559ecfcaec0?ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60',
        'https://images.unsplash.com/photo-1541961017774-22349e4a1262?ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60'
    ]
    import random
    return random.choice(default_images)

def activities_map(request):
    """完整地图页面 - 使用数据库数据"""
    try:
        events = Event.objects.filter(
            status='published',
            start_time__gte=timezone.now()
        )

        # 将活动数据转换为JSON格式，供前端使用
        events_data = []
        for event in events:
            # 确保经纬度存在
            if event.latitude and event.longitude:
                events_data.append({
                    'id': event.id,
                    'title': event.title,
                    'category': event.category.name if event.category else '其他',
                    'location': event.location,
                    'latitude': float(event.latitude),
                    'longitude': float(event.longitude),
                    'start_time': event.start_time.strftime('%Y-%m-%d %H:%M'),
                    'max_participants': event.max_participants,
                    'current_participants': event.current_participants,
                    'is_free': event.is_free,
                    'fee': float(event.fee) if not event.is_free else 0,
                })

        context = {
            'page_title': '活动地图 - 本地有约',
            'events': events,
            'events_json': json.dumps(events_data, ensure_ascii=False),
        }
        return render(request, 'activities_map.html', context)
    except Exception as e:
        context = {
            'page_title': '错误 - 本地有约',
            'error_message': '加载地图数据时出现错误'
        }
        return render(request, 'error.html', context, status=500)

@login_required
def register_event(request, event_id):
    """报名活动"""
    try:
        print(f"=== 报名请求开始 ===")
        print(f"用户: {request.user.username} (ID: {request.user.id})")
        print(f"活动ID: {event_id}")
        print(f"请求方法: {request.method}")
        print(f"请求头: {dict(request.headers)}")

        # 检查用户认证状态
        if not request.user.is_authenticated:
            print("用户未认证")
            return JsonResponse({
                'status': 'error',
                'message': '请先登录'
            })

        event = get_object_or_404(Event, id=event_id)
        print(f"找到活动: {event.title} (状态: {event.status})")

        # 检查活动是否可以报名
        if not event.can_register:
            print(f"活动无法报名 - 状态: {event.status}")
            return JsonResponse({
                'status': 'error',
                'message': '该活动目前无法报名'
            })

        # 检查是否已报名
        existing_registration = EventRegistration.objects.filter(
            event=event,
            user=request.user
        ).first()

        is_new_registration = False

        if existing_registration:
            if existing_registration.status == 'registered':
                print("用户已报名")
                return JsonResponse({
                    'status': 'error',
                    'message': '您已经报名了该活动'
                })
            else:
                # 重新报名
                existing_registration.status = 'registered'
                existing_registration.cancellation_time = None
                existing_registration.save()
                print("重新报名成功")
        else:
            # 创建新的报名记录
            EventRegistration.objects.create(
                event=event,
                user=request.user,
                status='registered'
            )
            is_new_registration = True
            print("新报名成功")

        # 更新当前报名人数
        event.current_participants = event.registrations.filter(status='registered').count()
        event.save()
        print(f"更新报名人数: {event.current_participants}")

        # 积分奖励逻辑
        points_earned = 0
        if is_new_registration:
            try:
                from .services import PointService
                success, point_message = PointService.handle_event_participation(request.user, event)
                if success:
                    point_transaction = PointTransaction.objects.filter(
                        user=request.user,
                        related_event=event,
                        source_type='event_join'
                    ).first()
                    if point_transaction:
                        points_earned = point_transaction.points
                        print(f"积分奖励: {points_earned}")
            except Exception as e:
                print(f"积分奖励失败: {str(e)}")

        response_data = {
            'status': 'success',
            'message': '报名成功！' + (f' 获得 {points_earned} 积分！' if points_earned else ''),
            'current_participants': event.current_participants
        }

        if points_earned:
            response_data['points_earned'] = points_earned

        print(f"报名成功，返回数据: {response_data}")
        print("=== 报名请求结束 ===")
        return JsonResponse(response_data)

    except Exception as e:
        print(f"!!! 报名异常: {str(e)}")
        import traceback
        traceback.print_exc()

        return JsonResponse({
            'status': 'error',
            'message': f'报名失败: {str(e)}'
        }, status=500)
@csrf_exempt
def get_user_location(request):
    """获取用户位置API"""
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            lat = data.get('lat')
            lng = data.get('lng')

            return JsonResponse({
                'status': 'success',
                'message': '位置信息已接收',
                'location': {'lat': lat, 'lng': lng}
            })
        except Exception as e:
            return JsonResponse({
                'status': 'error',
                'message': str(e)
            }, status=400)

    return JsonResponse({
        'status': 'error',
        'message': '仅支持POST请求'
    }, status=405)


def get_nearby_activities(request):
    """获取附近活动API - 基于数据库数据，支持搜索和筛选"""
    try:
        lat = request.GET.get('lat', 39.915)
        lng = request.GET.get('lng', 116.404)
        radius = float(request.GET.get('radius', 5))  # 默认5公里范围

        # 获取搜索和筛选参数
        search_term = request.GET.get('search', '')
        category_filter = request.GET.get('category', '')
        fee_filter = request.GET.get('fee', '')
        time_filter = request.GET.get('time', 'future')

        # 获取所有已发布的活动
        events = Event.objects.filter(status='published')

        # 搜索功能
        if search_term:
            events = events.filter(
                Q(title__icontains=search_term) |
                Q(description__icontains=search_term) |
                Q(location__icontains=search_term) |
                Q(category__name__icontains=search_term)
            )

        # 分类筛选
        if category_filter:
            events = events.filter(category__name=category_filter)

        # 费用筛选
        if fee_filter == 'free':
            events = events.filter(is_free=True)
        elif fee_filter == 'paid':
            events = events.filter(is_free=False)

        # 时间筛选
        now = timezone.now()
        if time_filter == 'future':
            events = events.filter(start_time__gte=now)
        elif time_filter == 'recent':
            week_ago = now - timedelta(days=7)
            events = events.filter(start_time__gte=week_ago)
        elif time_filter == 'past':
            events = events.filter(start_time__lt=now)
        # 'all' 不进行时间筛选

        # 将活动数据转换为前端需要的格式
        activities_data = []
        for event in events:
            # 确保有主要图片
            image_url = get_primary_image_url(event)

            # 计算平均评分
            avg_rating = event.reviews.aggregate(Avg('rating'))['rating__avg'] or 0

            # 确定活动状态
            status = 'active'
            if event.start_time < now:
                status = 'past'
            elif (event.start_time - now).total_seconds() < 3600:  # 1小时内开始
                status = 'soon'

            activities_data.append({
                'id': event.id,
                'title': event.title,
                'category': event.category.name if event.category else '其他',
                'distance': '附近',  # 在实际项目中应该计算真实距离
                'time': event.start_time.strftime('%m月%d日 %H:%M'),
                'rating': round(avg_rating, 1),
                'current_participants': event.current_participants,
                'max_participants': event.max_participants,
                'image': image_url,
                'location': {
                    'lat': float(event.latitude) if event.latitude else 39.915,
                    'lng': float(event.longitude) if event.longitude else 116.404
                },
                'address': event.location,
                'description': event.description[:100] + '...' if event.description and len(
                    event.description) > 100 else (event.description or ''),
                'is_free': event.is_free,
                'fee': float(event.fee) if not event.is_free else 0,
                'status': status,
                'views_count': event.views_count,
                'organizer': event.organizer.username
            })

        return JsonResponse({
            'status': 'success',
            'activities': activities_data,
            'count': len(activities_data),
            'user_location': {'lat': lat, 'lng': lng}
        })
    except Exception as e:
        import traceback
        traceback.print_exc()
        return JsonResponse({
            'status': 'error',
            'message': f'获取附近活动失败: {str(e)}'
        }, status=500)


def get_categories_api(request):
    """获取活动分类API"""
    try:
        categories = EventCategory.objects.filter(is_active=True)
        categories_data = [{'id': cat.id, 'name': cat.name} for cat in categories]

        return JsonResponse({
            'status': 'success',
            'categories': categories_data
        })
    except Exception as e:
        return JsonResponse({
            'status': 'error',
            'message': f'获取分类失败: {str(e)}'
        }, status=500)


def search_activities(request):
    """搜索活动API - 基于数据库数据"""
    try:
        query = request.GET.get('q', '')
        category = request.GET.get('category', 'all')

        # 基础查询
        events = Event.objects.filter(
            status='published',
            start_time__gte=timezone.now()
        )

        # 按分类筛选
        if category != 'all':
            events = events.filter(category__name=category)

        # 按关键词搜索
        if query:
            events = events.filter(
                Q(title__icontains=query) |
                Q(description__icontains=query) |
                Q(location__icontains=query)
            )

        # 获取所有分类
        categories = EventCategory.objects.filter(is_active=True)

        # 如果是AJAX请求，返回JSON
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            activities_data = []
            for event in events:
                primary_image = event.images.filter(is_primary=True).first()
                image_url = primary_image.image.url if primary_image else '/static/images/default-event.jpg'

                activities_data.append({
                    'id': event.id,
                    'title': event.title,
                    'category': event.category.name if event.category else '其他',
                    'distance': '附近',
                    'time': event.start_time.strftime('%m月%d日 %H:%M'),
                    'rating': 4.5,
                    'participants': f"{event.current_participants}/{event.max_participants}人",
                    'image': image_url,
                    'address': event.location,
                })

            return JsonResponse({
                'status': 'success',
                'activities': activities_data,
                'count': len(activities_data)
            })

        # 否则渲染模板
        context = {
            'page_title': f'搜索 "{query}" - 本地有约',
            'events': events,
            'categories': categories,
            'search_query': query,
            'current_category': category,
        }
        return render(request, 'activities.html', context)
    except Exception as e:
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return JsonResponse({
                'status': 'error',
                'message': f'搜索失败: {str(e)}'
            }, status=500)
        else:
            context = {
                'page_title': '错误 - 本地有约',
                'error_message': '搜索活动时出现错误'
            }
            return render(request, 'error.html', context, status=500)


from django.shortcuts import render, get_object_or_404
from .models import Event

#   详情
def activity_detail(request, event_id=None):
    """活动详情页面 - 支持带ID和不带ID两种访问方式"""
    try:
        if event_id is None:
            event = Event.objects.filter(status='published').first()
            if not event:
                context = {
                    'error_message': '没有找到活动数据，请检查活动ID是否正确'
                }
                return render(request, 'activity_detail.html', context)
        else:
            event = get_object_or_404(Event, id=event_id)

        # 增加浏览数
        event.views_count += 1
        event.save()

        # 获取活动图片
        event_images = event.images.all()

        # 获取活动评价
        reviews = event.reviews.all().order_by('-created_at')
        reviews_count = reviews.count()

        # 获取讨论区评论
        discussions = EventDiscussion.objects.filter(
            event=event,
            is_deleted=False,
            parent__isnull=True
        ).order_by('-is_pinned', '-created_at')
        discussions_count = discussions.count()

        # 计算平均评分
        avg_rating = reviews.aggregate(Avg('rating'))['rating__avg'] or 0

        # 检查用户是否已报名
        user_registered = False
        has_reviewed = False

        if request.user.is_authenticated:
            user_registered = EventRegistration.objects.filter(
                event=event,
                user=request.user,
                status='registered'
            ).exists()

            # 检查用户是否已评价
            has_reviewed = EventReview.objects.filter(
                event=event,
                user=request.user
            ).exists()

        # 检查是否可以报名
        can_register = (event.can_register and
                        not user_registered and
                        request.user.is_authenticated)

        context = {
            'page_title': f"{event.title} - 本地有约",
            'event': event,
            'event_images': event_images,
            'reviews': reviews,
            'discussions': discussions,
            'avg_rating': round(avg_rating, 1),
            'reviews_count': reviews_count,
            'discussions_count': discussions_count,
            'user_registered': user_registered,
            'has_reviewed': has_reviewed,  # 新增：用户是否已评价
            'can_register': can_register,
        }
        return render(request, 'activity_detail.html', context)

    except Exception as e:
        print(f"活动详情页错误: {str(e)}")
        context = {
            'error_message': f'加载活动详情时出现错误: {str(e)}'
        }
        return render(request, 'activity_detail.html', context, status=500)

from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
from django.contrib.auth.decorators import login_required
from django.db.models import Count
from .models import EventDiscussion, DiscussionLike, DiscussionDislike, Event

@csrf_exempt
@require_http_methods(["POST"])
@login_required
def like_discussion(request):
    """点赞讨论"""
    try:
        import json
        data = json.loads(request.body)
        discussion_id = data.get('discussion_id')
        action = data.get('action')

        discussion = EventDiscussion.objects.get(id=discussion_id)

        if action == 'like':
            like, created = DiscussionLike.objects.get_or_create(
                user=request.user,
                discussion=discussion
            )
            if created:
                discussion.likes_count += 1
                discussion.save()
                return JsonResponse({'success': True})
        else:  # unlike
            try:
                like = DiscussionLike.objects.get(user=request.user, discussion=discussion)
                like.delete()
                discussion.likes_count -= 1
                discussion.save()
                return JsonResponse({'success': True})
            except DiscussionLike.DoesNotExist:
                pass

        return JsonResponse({'success': False, 'message': '操作失败'})
    except EventDiscussion.DoesNotExist:
        return JsonResponse({'success': False, 'message': '评论不存在'})
    except Exception as e:
        return JsonResponse({'success': False, 'message': str(e)})


@csrf_exempt
@require_http_methods(["POST"])
@login_required
def dislike_discussion(request):
    """点踩讨论"""
    try:
        import json
        data = json.loads(request.body)
        discussion_id = data.get('discussion_id')
        action = data.get('action')  # 'dislike' or 'undislike'

        discussion = EventDiscussion.objects.get(id=discussion_id)

        if action == 'dislike':
            dislike, created = DiscussionDislike.objects.get_or_create(
                user=request.user,
                discussion=discussion
            )
            if created:
                discussion.dislikes_count += 1
                discussion.save()
                return JsonResponse({'success': True})
        else:  # undislike
            try:
                dislike = DiscussionDislike.objects.get(user=request.user, discussion=discussion)
                dislike.delete()
                discussion.dislikes_count -= 1
                discussion.save()
                return JsonResponse({'success': True})
            except DiscussionDislike.DoesNotExist:
                pass

        return JsonResponse({'success': False, 'message': '操作失败'})
    except EventDiscussion.DoesNotExist:
        return JsonResponse({'success': False, 'message': '评论不存在'})
    except Exception as e:
        return JsonResponse({'success': False, 'message': str(e)})


@csrf_exempt
@require_http_methods(["POST"])
@login_required
def create_discussion(request):
    """创建评论或回复"""
    try:
        import json
        data = json.loads(request.body)
        content = data.get('content')
        event_id = data.get('event_id')
        parent_id = data.get('parent_id')

        event = Event.objects.get(id=event_id)

        discussion = EventDiscussion.objects.create(
            user=request.user,
            event=event,
            content=content,
            parent_id=parent_id
        )

        # ============ 新增：评论创建后立即奖励积分 ============
        try:
            from .services import PointService
            success, message = PointService.handle_comment_creation(
                request.user, discussion, is_discussion=True
            )
            if success:
                print(f"✅ 评论积分奖励成功: {message}")
            else:
                print(f"⚠️ 评论积分奖励失败: {message}")
        except Exception as e:
            print(f"❌ 评论积分奖励异常: {str(e)}")
        # ============ 积分奖励结束 ============

        return JsonResponse({
            'success': True,
            'discussion': {
                'id': discussion.id,
                'user': {'username': request.user.username},
                'content': content,
                'created_at': discussion.created_at.isoformat(),
                'likes_count': 0,
                'dislikes_count': 0,
                'is_pinned': discussion.is_pinned,
                'can_delete': True  # 用户只能删除自己的评论
            }
        })
    except Exception as e:
        return JsonResponse({'success': False, 'message': str(e)})


@csrf_exempt
@require_http_methods(["DELETE"])
@login_required
def delete_discussion(request, discussion_id):
    """删除评论"""
    try:
        discussion = EventDiscussion.objects.get(id=discussion_id)

        # 检查权限：评论作者或活动组织者可以删除
        if discussion.user != request.user and discussion.event.organizer != request.user:
            return JsonResponse({'success': False, 'message': '没有权限删除此评论'})

        discussion.delete()
        return JsonResponse({'success': True})
    except EventDiscussion.DoesNotExist:
        return JsonResponse({'success': False, 'message': '评论不存在'})
    except Exception as e:
        return JsonResponse({'success': False, 'message': str(e)})


def get_discussions(request, event_id):
    """获取活动的讨论列表"""
    try:
        discussions = EventDiscussion.objects.filter(
            event_id=event_id,
            parent__isnull=True,
            is_deleted=False
        ).select_related('user').prefetch_related(
            'replies__user',
            'likes',
            'dislikes'
        ).annotate(
            replies_count=Count('replies')
        ).order_by('-is_pinned', '-created_at')

        discussions_data = []
        for discussion in discussions:
            # 检查当前用户是否点赞/踩过
            user_liked = False
            user_disliked = False
            if request.user.is_authenticated:
                user_liked = discussion.likes.filter(user=request.user).exists()
                user_disliked = discussion.dislikes.filter(user=request.user).exists()

            discussion_data = {
                'id': discussion.id,
                'user': {'username': discussion.user.username},
                'content': discussion.content,
                'likes_count': discussion.likes_count,
                'dislikes_count': discussion.dislikes_count,
                'is_pinned': discussion.is_pinned,
                'created_at': discussion.created_at.isoformat(),
                'user_liked': user_liked,
                'user_disliked': user_disliked,
                'can_delete': discussion.user == request.user or discussion.event.organizer == request.user,
                'replies': []
            }

            # 添加回复
            for reply in discussion.replies.filter(is_deleted=False).order_by('created_at')[:10]:  # 只加载前10条回复
                reply_user_liked = False
                reply_user_disliked = False
                if request.user.is_authenticated:
                    reply_user_liked = reply.likes.filter(user=request.user).exists()
                    reply_user_disliked = reply.dislikes.filter(user=request.user).exists()

                discussion_data['replies'].append({
                    'id': reply.id,
                    'user': {'username': reply.user.username},
                    'content': reply.content,
                    'likes_count': reply.likes_count,
                    'dislikes_count': reply.dislikes_count,
                    'created_at': reply.created_at.isoformat(),
                    'user_liked': reply_user_liked,
                    'user_disliked': reply_user_disliked,
                    'can_delete': reply.user == request.user or discussion.event.organizer == request.user,
                })

            discussions_data.append(discussion_data)

        return JsonResponse({
            'success': True,
            'discussions': discussions_data
        })
    except Exception as e:
        return JsonResponse({'success': False, 'message': str(e)})

@csrf_exempt
@require_http_methods(["POST"])
@login_required
def register_event_api(request):
    """报名活动 API - 处理AJAX请求"""
    try:
        print(f"=== API报名请求开始 ===")
        print(f"用户: {request.user.username}")
        print(f"请求数据: {request.body}")

        data = json.loads(request.body)
        event_id = data.get('event_id')

        if not event_id:
            return JsonResponse({
                'status': 'error',
                'message': '缺少活动ID'
            })

        event = get_object_or_404(Event, id=event_id)
        print(f"找到活动: {event.title}")

        # 检查活动是否可以报名
        if not event.can_register:
            return JsonResponse({
                'status': 'error',
                'message': '该活动目前无法报名'
            })

        # 检查是否已报名
        existing_registration = EventRegistration.objects.filter(
            event=event,
            user=request.user
        ).first()

        is_new_registration = False

        if existing_registration:
            if existing_registration.status == 'registered':
                return JsonResponse({
                    'status': 'error',
                    'message': '您已经报名了该活动'
                })
            else:
                # 重新报名
                existing_registration.status = 'registered'
                existing_registration.cancellation_time = None
                existing_registration.save()
        else:
            # 创建新的报名记录
            EventRegistration.objects.create(
                event=event,
                user=request.user,
                status='registered'
            )
            is_new_registration = True

        # 更新当前报名人数
        event.current_participants = event.registrations.filter(status='registered').count()
        event.save()

        # 积分奖励逻辑
        points_earned = 0
        if is_new_registration:
            try:
                from .services import PointService
                success, point_message = PointService.handle_event_participation(request.user, event)
                if success:
                    point_transaction = PointTransaction.objects.filter(
                        user=request.user,
                        related_event=event,
                        source_type='event_join'
                    ).first()
                    if point_transaction:
                        points_earned = point_transaction.points
            except Exception as e:
                print(f"积分奖励失败: {str(e)}")

        response_data = {
            'status': 'success',
            'message': '报名成功！' + (f' 获得 {points_earned} 积分！' if points_earned else ''),
            'current_participants': event.current_participants
        }

        if points_earned:
            response_data['points_earned'] = points_earned

        print(f"API报名成功: {response_data}")
        return JsonResponse(response_data)

    except Exception as e:
        print(f"!!! API报名异常: {str(e)}")
        import traceback
        traceback.print_exc()

        return JsonResponse({
            'status': 'error',
            'message': f'报名失败: {str(e)}'
        }, status=500)

# 添加获取报名人数的API
def get_event_participants(request, event_id):
    try:
        event = Event.objects.get(id=event_id)
        return JsonResponse({
            'success': True,
            'current_participants': event.current_participants,
            'max_participants': event.max_participants
        })
    except Event.DoesNotExist:
        return JsonResponse({'success': False, 'message': '活动不存在'})
@csrf_exempt
@require_http_methods(["POST"])
@login_required
def cancel_registration_api(request):
    """取消报名活动 API"""
    try:
        data = json.loads(request.body)
        event_id = data.get('event_id')
        event = get_object_or_404(Event, id=event_id)

        # 查找报名记录
        registration = EventRegistration.objects.filter(
            event=event,
            user=request.user,
            status='registered'
        ).first()

        if not registration:
            return JsonResponse({
                'success': False,
                'message': '您还没有报名该活动'
            })

        # 取消报名
        registration.status = 'cancelled'
        registration.cancellation_time = timezone.now()
        registration.save()

        # 更新当前报名人数
        event.current_participants = event.registrations.filter(status='registered').count()
        event.save()

        return JsonResponse({
            'success': True,
            'message': '取消报名成功！',
            'current_participants': event.current_participants
        })
    except Exception as e:
        return JsonResponse({
            'success': False,
            'message': f'取消报名失败: {str(e)}'
        }, status=500)
@method_decorator(csrf_exempt, name='dispatch')
class EventReviewView(View):
    """活动评价API"""

    def post(self, request):
        """提交评价"""
        if not request.user.is_authenticated:
            return JsonResponse({'success': False, 'message': '请先登录'})

        try:
            data = json.loads(request.body)
            event_id = data.get('event_id')
            rating = data.get('rating')
            comment = data.get('comment', '')

            # 验证参数
            if not all([event_id, rating]):
                return JsonResponse({'success': False, 'message': '缺少必要参数'})

            try:
                event = Event.objects.get(id=event_id)
            except Event.DoesNotExist:
                return JsonResponse({'success': False, 'message': '活动不存在'})

            # 检查用户是否报名了该活动
            if not EventRegistration.objects.filter(
                    event=event,
                    user=request.user,
                    status__in=['registered', 'attended']
            ).exists():
                return JsonResponse({'success': False, 'message': '只有报名用户才能评价'})

            # 创建或更新评价
            review, created = EventReview.objects.update_or_create(
                event=event,
                user=request.user,
                defaults={
                    'rating': rating,
                    'comment': comment
                }
            )

            # 计算新的平均评分
            avg_rating = EventReview.objects.filter(event=event).aggregate(
                avg_rating=Avg('rating')
            )['avg_rating'] or 0

            reviews_count = EventReview.objects.filter(event=event).count()

            return JsonResponse({
                'success': True,
                'message': '评价提交成功',
                'avg_rating': round(avg_rating, 1),
                'reviews_count': reviews_count,
                'review': {
                    'id': review.id,
                    'rating': review.rating,
                    'comment': review.comment,
                    'created_at': review.created_at.isoformat()
                }
            })

        except Exception as e:
            return JsonResponse({'success': False, 'message': f'服务器错误: {str(e)}'})

    def get(self, request):
        """检查用户是否已评价"""
        if not request.user.is_authenticated:
            return JsonResponse({'has_reviewed': False})

        event_id = request.GET.get('event_id')
        if not event_id:
            return JsonResponse({'success': False, 'message': '缺少活动ID'})

        try:
            event = Event.objects.get(id=event_id)
            has_reviewed = EventReview.objects.filter(
                event=event,
                user=request.user
            ).exists()

            return JsonResponse({
                'has_reviewed': has_reviewed,
                'success': True
            })

        except Event.DoesNotExist:
            return JsonResponse({'success': False, 'message': '活动不存在'})
        except Exception as e:
            return JsonResponse({'success': False, 'message': f'服务器错误: {str(e)}'})

@csrf_exempt
@require_http_methods(["POST"])
def submit_review(request):
    """提交评价"""
    if not request.user.is_authenticated:
        return JsonResponse({'success': False, 'message': '请先登录'})

    try:
        data = json.loads(request.body)
        event_id = data.get('event_id')
        rating = data.get('rating')
        comment = data.get('comment', '')

        if not all([event_id, rating]):
            return JsonResponse({'success': False, 'message': '缺少必要参数'})

        try:
            event = Event.objects.get(id=event_id)
        except Event.DoesNotExist:
            return JsonResponse({'success': False, 'message': '活动不存在'})

        # 检查用户是否报名了该活动
        if not EventRegistration.objects.filter(
                event=event,
                user=request.user,
                status__in=['registered', 'attended']
        ).exists():
            return JsonResponse({'success': False, 'message': '只有报名用户才能评价'})

        # 创建或更新评价
        review, created = EventReview.objects.update_or_create(
            event=event,
            user=request.user,
            defaults={
                'rating': rating,
                'comment': comment
            }
        )

        # 计算新的平均评分
        avg_rating = EventReview.objects.filter(event=event).aggregate(
            avg_rating=Avg('rating')
        )['avg_rating'] or 0

        reviews_count = EventReview.objects.filter(event=event).count()

        return JsonResponse({
            'success': True,
            'message': '评价提交成功',
            'avg_rating': round(avg_rating, 1),
            'reviews_count': reviews_count
        })

    except Exception as e:
        return JsonResponse({'success': False, 'message': f'服务器错误: {str(e)}'})

#评分提交的 API 视图

@csrf_exempt
def check_review_status(request):
    """检查评价状态"""
    if not request.user.is_authenticated:
        return JsonResponse({'has_reviewed': False})

    event_id = request.GET.get('event_id')
    if not event_id:
        return JsonResponse({'success': False, 'message': '缺少活动ID'})

    try:
        event = Event.objects.get(id=event_id)
        has_reviewed = EventReview.objects.filter(
            event=event,
            user=request.user
        ).exists()

        return JsonResponse({
            'has_reviewed': has_reviewed,
            'success': True
        })

    except Event.DoesNotExist:
        return JsonResponse({'success': False, 'message': '活动不存在'})
    except Exception as e:
        return JsonResponse({'success': False, 'message': f'服务器错误: {str(e)}'})

from django.db.models import Count, Q
import json
# 社区
def community_home(request):
    """社区首页 """
    # 获取所有用户
    all_users = CustomUser.objects.all().order_by('-date_joined')  # 显示用户
    # 获取热门帖子
    hot_posts = CommunityPost.objects.filter(is_active=True,status='published').annotate(
        total_likes=Count('likes'),
        total_comments=Count('comments')
    ).order_by('-total_likes', '-views_count')[:6]

    # 获取最新帖子
    latest_posts = CommunityPost.objects.filter(is_active=True,status='published').order_by('-created_at')[:10]

    # 获取置顶帖子
    pinned_posts = CommunityPost.objects.filter(is_active=True,status='published', is_pinned=True).order_by('-created_at')
    active_users = CustomUser.objects.filter(
        is_active=True,
        community_posts__is_active=True
    ).annotate(
        post_count=Count('community_posts')
    ).filter(
        post_count__gt=0
    ).distinct().order_by('-post_count')[:6]

    # 获取热门活动
    popular_events = Event.objects.filter(
        status='published',
        start_time__gte=timezone.now()
    ).order_by('-views_count')[:3]

    context = {
        'page_title': '社区讨论 - 本地有约',
        'all_users': all_users,  # 用户
        'hot_posts': hot_posts,
        'latest_posts': latest_posts,
        'pinned_posts': pinned_posts,
        'active_users': active_users,
        'popular_events': popular_events,
        'user': request.user,
    }

    return render(request, 'community/community_home.html', context)


def community_posts(request):
    """帖子列表页面"""
    try:
        posts = CommunityPost.objects.filter(is_active=True)

        # 筛选条件
        post_type = request.GET.get('type', '')
        category_id = request.GET.get('category', '')
        sort_by = request.GET.get('sort', 'newest')

        if post_type:
            posts = posts.filter(post_type=post_type)

        if category_id:
            posts = posts.filter(event__category_id=category_id)

        # 排序
        if sort_by == 'hot':
            posts = posts.annotate(
                total_likes=Count('likes'),
                total_comments=Count('comments')
            ).order_by('-total_likes', '-views_count')
        elif sort_by == 'commented':
            posts = posts.annotate(comment_count=Count('comments')).order_by('-comment_count')
        else:  # newest
            posts = posts.order_by('-created_at')

        # 分页
        paginator = Paginator(posts, 15)
        page_number = request.GET.get('page', 1)
        page_obj = paginator.get_page(page_number)

        categories = EventCategory.objects.filter(is_active=True)

        context = {
            'page_title': '社区帖子 - 本地有约',
            'page_obj': page_obj,
            'posts': page_obj,
            'categories': categories,
            'selected_type': post_type,
            'selected_category': category_id,
            'selected_sort': sort_by,
            'total_posts': paginator.count,
        }
        return render(request, 'community/community_posts.html', context)
    except Exception as e:
        context = {
            'page_title': '错误 - 本地有约',
            'error_message': '加载帖子列表时出现错误'
        }
        return render(request, 'error.html', context, status=500)


def create_post(request):
    """创建帖子 - 支持保存草稿"""
    if request.method == 'POST':
        try:
            title = request.POST.get('title')
            content = request.POST.get('content')
            post_type = request.POST.get('post_type', 'discussion')
            event_id = request.POST.get('event_id')
            is_draft = request.POST.get('is_draft') == 'true'  # 是否为草稿

            if not title or not content:
                return JsonResponse({
                    'status': 'error',
                    'message': '标题和内容不能为空'
                })

            if is_draft:
                # 保存为草稿
                draft = PostDraft.objects.create(
                    title=title,
                    content=content,
                    author=request.user,
                    post_type=post_type,
                    event_id=event_id if event_id else None,
                    status='draft'
                )

                return JsonResponse({
                    'status': 'success',
                    'message': '草稿保存成功',
                    'draft_id': draft.id,
                    'is_draft': True
                })
            else:
                # 发布正式帖子
                post = CommunityPost.objects.create(
                    title=title,
                    content=content,
                    author=request.user,
                    post_type=post_type,
                    event_id=event_id if event_id else None,
                    status='published'
                )

                # ✅ 新增：发布帖子积分奖励
                try:
                    from .services import PointService
                    success, message = PointService.handle_post_creation(request.user, post)
                    if success:
                        print(f"✅ 帖子发布积分奖励成功: {message}")
                    else:
                        print(f"⚠️ 帖子发布积分奖励失败: {message}")
                except Exception as e:
                    print(f"❌ 帖子发布积分奖励异常: {str(e)}")

                # 创建用户动态
                UserActivity.objects.create(
                    user=request.user,
                    activity_type='post_created',
                    target_post=post
                )

                return JsonResponse({
                    'status': 'success',
                    'message': '帖子发布成功',
                    'post_id': post.id,
                    'is_draft': False
                })
        except Exception as e:
            return JsonResponse({
                'status': 'error',
                'message': f'操作失败: {str(e)}'
            })

    # GET 请求显示创建页面
    events = Event.objects.filter(status='published', start_time__gte=timezone.now())
    context = {
        'page_title': '发布帖子 - 本地有约',
        'events': events,
    }
    return render(request, 'community/create_post.html', context)


@login_required
@require_POST
def admin_approve_event(request, event_id):
    """管理员审核通过活动 - 确保触发积分奖励"""
    if not request.user.is_staff:
        return JsonResponse({'success': False, 'message': '权限不足'})

    try:
        event = get_object_or_404(Event, id=event_id)

        # 记录旧状态
        old_status = event.status
        print(f"🔍 [管理员审核] 活动: {event.title}, 当前状态: {old_status}")

        # 只有待审核的活动才能被审核通过
        if event.status != 'pending':
            return JsonResponse({
                'success': False,
                'message': f'活动状态为 {event.get_status_display()}，无法审核通过'
            })

        # 更新状态 - 这会触发 save() 方法
        event.status = 'published'
        event.save()  # 这会触发状态变化检测和积分奖励

        print(f"✅ [管理员审核] 活动状态已更新: {old_status} -> {event.status}")

        return JsonResponse({
            'success': True,
            'message': '活动审核通过',
            'new_status': event.status,
            'new_status_display': event.get_status_display()
        })

    except Exception as e:
        print(f"❌ [管理员审核] 异常: {str(e)}")
        return JsonResponse({
            'success': False,
            'message': f'审核失败: {str(e)}'
        })



def post_detail(request, post_id):
    """帖子详情"""
    post = get_object_or_404(CommunityPost, id=post_id, is_active=True)

    # 增加浏览数
    post.views_count += 1
    post.save()

    # 获取评论
    comments = post.comments.filter(parent__isnull=True).order_by('created_at')

    # 检查用户是否点赞
    user_liked = False
    if request.user.is_authenticated:
        user_liked = PostLike.objects.filter(post=post, user=request.user).exists()

    # 获取相关帖子 - 根据关联的活动来显示
    related_posts = []
    if post.event:
        # 如果帖子有关联的活动，显示同活动的其他帖子
        related_posts = CommunityPost.objects.filter(
            event=post.event,
            is_active=True
        ).exclude(id=post.id).select_related('author', 'event').order_by('-created_at')[:5]
    else:
        # 如果没有关联活动，显示同分类的其他帖子
        related_posts = CommunityPost.objects.filter(
            post_type=post.post_type,
            is_active=True
        ).exclude(id=post.id).select_related('author', 'event').order_by('-created_at')[:5]

    # 获取粉丝数
    followers_count = Follow.objects.filter(following=post.author).count()

    context = {
        'page_title': f"{post.title} - 本地有约",
        'post': post,
        'comments': comments,
        'user_liked': user_liked,
        'related_posts': related_posts,
        'followers_count': followers_count,
    }
    return render(request, 'community/post_detail.html', context)

#删除评论
@csrf_exempt
@require_http_methods(["DELETE"])
@login_required
def delete_comment(request, comment_id):
    """删除评论"""
    try:
        comment = get_object_or_404(PostComment, id=comment_id)

        # 检查权限：只有评论作者可以删除
        if comment.author != request.user:
            return JsonResponse({
                'success': False,
                'message': '没有权限删除此评论'
            })

        # 获取帖子ID用于更新评论计数
        post = comment.post

        # 删除评论
        comment.delete()

        # 更新帖子评论数
        post.comments_count = post.comments.count()
        post.save()

        return JsonResponse({
            'success': True,
            'message': '评论删除成功'
        })
    except PostComment.DoesNotExist:
        return JsonResponse({
            'success': False,
            'message': '评论不存在'
        })
    except Exception as e:
        return JsonResponse({
            'success': False,
            'message': f'删除失败: {str(e)}'
        })

@login_required
def add_comment(request, post_id):
    """添加评论"""
    if request.method == 'POST':
        try:
            post = get_object_or_404(CommunityPost, id=post_id, is_active=True)
            content = request.POST.get('content')
            parent_id = request.POST.get('parent_id')

            if not content:
                return JsonResponse({
                    'status': 'error',
                    'message': '评论内容不能为空'
                })

            comment = PostComment.objects.create(
                post=post,
                author=request.user,
                content=content,
                parent_id=parent_id if parent_id else None
            )

            # 更新帖子评论数
            post.comments_count = post.comments.count()
            post.save()

            # 创建用户动态
            UserActivity.objects.create(
                user=request.user,
                activity_type='comment_created',
                target_post=post,
                target_comment=comment
            )

            return JsonResponse({
                'status': 'success',
                'message': '评论发布成功',
                'comment_id': comment.id
            })
        except Exception as e:
            return JsonResponse({
                'status': 'error',
                'message': f'评论失败: {str(e)}'
            })

    return JsonResponse({
        'status': 'error',
        'message': '无效的请求方法'
    })


@login_required
def toggle_post_like(request, post_id):
    """点赞/取消点赞帖子"""
    try:
        post = get_object_or_404(CommunityPost, id=post_id, is_active=True)
        like, created = PostLike.objects.get_or_create(post=post, user=request.user)

        if not created:
            # 如果已经点赞，则取消点赞
            like.delete()
            liked = False
        else:
            liked = True

        # 更新点赞数
        post.likes_count = post.likes.count()
        post.save()

        return JsonResponse({
            'status': 'success',
            'liked': liked,
            'likes_count': post.likes_count
        })
    except Exception as e:
        return JsonResponse({
            'status': 'error',
            'message': str(e)
        })


@login_required
def toggle_comment_like(request, comment_id):
    """点赞/取消点赞评论"""
    try:
        comment = get_object_or_404(PostComment, id=comment_id)
        like, created = CommentLike.objects.get_or_create(comment=comment, user=request.user)

        if not created:
            like.delete()
            liked = False
        else:
            liked = True

        # 更新点赞数
        comment.likes_count = comment.likes.count()
        comment.save()

        return JsonResponse({
            'status': 'success',
            'liked': liked,
            'likes_count': comment.likes_count
        })
    except Exception as e:
        return JsonResponse({
            'status': 'error',
            'message': str(e)
        })


# 社交功能视图
@login_required
def toggle_follow(request, user_id):
    """关注/取消关注用户"""
    try:
        target_user = get_object_or_404(CustomUser, id=user_id)

        if request.user == target_user:
            return JsonResponse({
                'status': 'error',
                'message': '不能关注自己'
            })

        follow, created = Follow.objects.get_or_create(
            follower=request.user,
            following=target_user
        )

        if not created:
            follow.delete()
            following = False
        else:
            following = True

        # 更新关注数
        followers_count = Follow.objects.filter(following=target_user).count()
        following_count = Follow.objects.filter(follower=target_user).count()

        return JsonResponse({
            'status': 'success',
            'following': following,
            'followers_count': followers_count,
            'following_count': following_count
        })
    except Exception as e:
        return JsonResponse({
            'status': 'error',
            'message': str(e)
        })


@login_required
def message_list(request):
    """私信列表"""
    # 获取最近的对话
    sent_messages = UserMessage.objects.filter(sender=request.user).values('receiver').distinct()
    received_messages = UserMessage.objects.filter(receiver=request.user).values('sender').distinct()

    user_ids = set()
    for msg in sent_messages:
        user_ids.add(msg['receiver'])
    for msg in received_messages:
        user_ids.add(msg['sender'])

    conversations = []
    for user_id in user_ids:
        user = CustomUser.objects.get(id=user_id)
        last_message = UserMessage.objects.filter(
            Q(sender=request.user, receiver=user) | Q(sender=user, receiver=request.user)
        ).order_by('-created_at').first()

        unread_count = UserMessage.objects.filter(
            sender=user, receiver=request.user, is_read=False
        ).count()

        conversations.append({
            'user': user,
            'last_message': last_message,
            'unread_count': unread_count
        })

    # 按最后消息时间排序
    conversations.sort(key=lambda x: x['last_message'].created_at if x['last_message'] else timezone.now(),
                       reverse=True)

    context = {
        'page_title': '私信 - 本地有约',
        'conversations': conversations,
    }
    return render(request, 'social/message_list.html', context)


@login_required
def message_thread(request, user_id):
    """私信对话"""
    other_user = get_object_or_404(CustomUser, id=user_id)

    # 标记为已读
    UserMessage.objects.filter(sender=other_user, receiver=request.user, is_read=False).update(is_read=True)

    # 获取消息
    messages = UserMessage.objects.filter(
        Q(sender=request.user, receiver=other_user) | Q(sender=other_user, receiver=request.user)
    ).order_by('created_at')

    context = {
        'page_title': f'与{other_user.username}的对话 - 本地有约',
        'other_user': other_user,
        'messages': messages,
    }
    return render(request, 'social/message_thread.html', context)


@login_required
def send_message(request):
    """发送私信"""
    if request.method == 'POST':
        try:
            receiver_id = request.POST.get('receiver_id')
            content = request.POST.get('content')

            if not content:
                return JsonResponse({
                    'status': 'error',
                    'message': '消息内容不能为空'
                })

            receiver = get_object_or_404(CustomUser, id=receiver_id)

            message = UserMessage.objects.create(
                sender=request.user,
                receiver=receiver,
                content=content
            )

            return JsonResponse({
                'status': 'success',
                'message': '消息发送成功',
                'message_id': message.id
            })
        except Exception as e:
            return JsonResponse({
                'status': 'error',
                'message': f'发送失败: {str(e)}'
            })

    return JsonResponse({
        'status': 'error',
        'message': '无效的请求方法'
    })

@login_required
def message_conversations_json(request):
    """获取私信对话列表的JSON数据 - 用于异步刷新"""
    try:
        # 获取最近的对话
        sent_messages = UserMessage.objects.filter(sender=request.user).values('receiver').distinct()
        received_messages = UserMessage.objects.filter(receiver=request.user).values('sender').distinct()

        user_ids = set()
        for msg in sent_messages:
            user_ids.add(msg['receiver'])
        for msg in received_messages:
            user_ids.add(msg['sender'])

        conversations = []
        for user_id in user_ids:
            user = CustomUser.objects.get(id=user_id)
            last_message = UserMessage.objects.filter(
                Q(sender=request.user, receiver=user) | Q(sender=user, receiver=request.user)
            ).order_by('-created_at').first()

            unread_count = UserMessage.objects.filter(
                sender=user, receiver=request.user, is_read=False
            ).count()

            # 获取用户职业信息
            occupation = ""
            try:
                if hasattr(user, 'profile') and user.profile.occupation:
                    occupation = user.profile.occupation
            except:
                pass

            conversations.append({
                'user': {
                    'id': user.id,
                    'username': user.username,
                    'avatar_url': user.avatar.url if user.avatar else '/static/images/default-avatar.jpg',
                    'occupation': occupation
                },
                'last_message_content': last_message.content if last_message else "",
                'last_message_time': last_message.created_at.strftime('%Y-%m-%d %H:%M:%S') if last_message else "",
                'last_message_sender_id': last_message.sender.id if last_message else None,
                'unread_count': unread_count,
                'message_count': UserMessage.objects.filter(
                    Q(sender=request.user, receiver=user) | Q(sender=user, receiver=request.user)
                ).count()
            })

        # 按最后消息时间排序
        conversations.sort(key=lambda x: x.get('last_message_time', ''), reverse=True)

        return JsonResponse({
            'success': True,
            'conversations': conversations
        })
    except Exception as e:
        return JsonResponse({
            'success': False,
            'message': f'加载对话列表失败: {str(e)}'
        }, status=500)
# 推荐用户
@login_required
def recommended_users_api(request):
    """获取推荐用户API - 基于用户发帖兴趣"""
    try:
        # 获取当前用户发布的帖子类型
        user_posts = CommunityPost.objects.filter(author=request.user, is_active=True)

        # 分析用户的发帖兴趣（按帖子类型和关联的活动分类）
        user_interests = set()

        for post in user_posts:
            if post.post_type:
                user_interests.add(f"post_type:{post.post_type}")
            if post.event and post.event.category:
                user_interests.add(f"category:{post.event.category.name}")

        # 如果没有发帖历史，使用默认推荐（活跃用户）
        if not user_interests:
            # 推荐最近活跃的用户
            recommended_users = CustomUser.objects.filter(
                is_active=True
            ).exclude(
                id=request.user.id  # 排除自己
            ).annotate(
                posts_count=Count('community_posts', filter=Q(community_posts__is_active=True)),
                events_count=Count('organized_events', filter=Q(organized_events__status='published'))
            ).filter(
                posts_count__gt=0  # 至少发过一个帖子
            ).order_by('-date_joined')[:6]

            users_data = []
            for user in recommended_users:
                users_data.append({
                    'id': user.id,
                    'username': user.username,
                    'avatar_url': user.avatar.url if user.avatar else '/static/images/default-avatar.jpg',
                    'posts_count': user.posts_count,
                    'events_count': user.events_count,
                    'common_interests': None
                })

            return JsonResponse({
                'success': True,
                'users': users_data
            })

        # 基于兴趣推荐用户
        recommended_users = []

        # 方法1: 按帖子类型推荐
        for interest in user_interests:
            if interest.startswith('post_type:'):
                post_type = interest.split(':')[1]
                users_with_same_type = CustomUser.objects.filter(
                    community_posts__post_type=post_type,
                    community_posts__is_active=True,
                    is_active=True
                ).exclude(
                    id=request.user.id
                ).distinct()

                for user in users_with_same_type:
                    if user not in [u['user'] for u in recommended_users]:
                        recommended_users.append({
                            'user': user,
                            'reason': f"同样发布{post_type}类型帖子"
                        })

        # 方法2: 按活动分类推荐
        for interest in user_interests:
            if interest.startswith('category:'):
                category_name = interest.split(':')[1]
                users_with_same_category = CustomUser.objects.filter(
                    community_posts__event__category__name=category_name,
                    community_posts__is_active=True,
                    is_active=True
                ).exclude(
                    id=request.user.id
                ).distinct()

                for user in users_with_same_category:
                    if user not in [u['user'] for u in recommended_users]:
                        recommended_users.append({
                            'user': user,
                            'reason': f"同样关注{category_name}类活动"
                        })

        # 去重并限制数量
        seen_users = set()
        unique_recommended_users = []

        for rec in recommended_users:
            if rec['user'].id not in seen_users:
                seen_users.add(rec['user'].id)
                unique_recommended_users.append(rec)

        # 如果推荐用户不足，补充活跃用户
        if len(unique_recommended_users) < 6:
            additional_users = CustomUser.objects.filter(
                is_active=True
            ).exclude(
                id__in=seen_users.union({request.user.id})
            ).annotate(
                posts_count=Count('community_posts', filter=Q(community_posts__is_active=True)),
                events_count=Count('organized_events', filter=Q(organized_events__status='published'))
            ).filter(
                posts_count__gt=0
            ).order_by('-date_joined')[:6 - len(unique_recommended_users)]

            for user in additional_users:
                unique_recommended_users.append({
                    'user': user,
                    'reason': "活跃用户"
                })

        # 准备返回数据
        users_data = []
        for rec in unique_recommended_users[:6]:  # 最多返回6个
            user = rec['user']
            users_data.append({
                'id': user.id,
                'username': user.username,
                'avatar_url': user.avatar.url if user.avatar else '/static/images/default-avatar.jpg',
                'posts_count': user.community_posts.filter(is_active=True).count(),
                'events_count': user.organized_events.filter(status='published').count(),
                'common_interests': rec['reason']
            })

        return JsonResponse({
            'success': True,
            'users': users_data
        })

    except Exception as e:
        return JsonResponse({
            'success': False,
            'message': f'获取推荐用户失败: {str(e)}'
        }, status=500)
def user_activities(request):
    """用户动态"""
    activities = UserActivity.objects.select_related(
        'user', 'target_event', 'target_post', 'target_comment'
    ).order_by('-created_at')

    # 如果登录，可以只显示关注用户的动态
    if request.user.is_authenticated:
        following_ids = Follow.objects.filter(follower=request.user).values_list('following_id', flat=True)
        activities = activities.filter(user_id__in=following_ids)

    # 分页
    paginator = Paginator(activities, 20)
    page_number = request.GET.get('page', 1)
    page_obj = paginator.get_page(page_number)

    context = {
        'page_title': '用户动态 - 本地有约',
        'page_obj': page_obj,
        'activities': page_obj,
    }
    return render(request, 'social/user_activities.html', context)


def user_profile(request, user_id):
    """用户主页"""
    user = get_object_or_404(CustomUser, id=user_id)

    # 获取用户资料
    try:
        profile = user.profile
    except UserProfile.DoesNotExist:
        profile = UserProfile.objects.create(user=user)

    # 统计信息
    followers_count = Follow.objects.filter(following=user).count()
    following_count = Follow.objects.filter(follower=user).count()

    # 活动统计
    events_organized = Event.objects.filter(organizer=user).count()
    events_attended = EventRegistration.objects.filter(user=user).count()
    posts_count = CommunityPost.objects.filter(author=user, is_active=True).count()

    # 最近的活动
    recent_events = EventRegistration.objects.filter(user=user).select_related('event').order_by('-registration_time')[
        :5]
    recent_posts = CommunityPost.objects.filter(author=user, is_active=True).order_by('-created_at')[:5]

    # 检查是否已关注
    is_following = False
    if request.user.is_authenticated:
        is_following = Follow.objects.filter(follower=request.user, following=user).exists()

    context = {
        'page_title': f"{user.username}的主页 - 本地有约",
        'profile_user': user,
        'profile': profile,
        'followers_count': followers_count,
        'following_count': following_count,
        'events_organized': events_organized,
        'events_attended': events_attended,
        'posts_count': posts_count,
        'recent_events': recent_events,
        'recent_posts': recent_posts,
        'is_following': is_following,
    }
    return render(request, 'social/user_profile.html', context)

#草稿
@login_required
def draft_list(request):
    """草稿箱列表"""
    drafts = PostDraft.objects.filter(author=request.user).order_by('-updated_at')

    context = {
        'page_title': '我的草稿箱 - 本地有约',
        'drafts': drafts,
    }
    return render(request, 'community/draft_list.html', context)


@login_required
def edit_draft(request, draft_id):
    """编辑草稿"""
    draft = get_object_or_404(PostDraft, id=draft_id, author=request.user)

    if request.method == 'POST':
        try:
            title = request.POST.get('title')
            content = request.POST.get('content')
            post_type = request.POST.get('post_type', 'discussion')
            event_id = request.POST.get('event_id')
            action = request.POST.get('action')  # 'save' or 'publish'

            if not title or not content:
                return JsonResponse({
                    'status': 'error',
                    'message': '标题和内容不能为空'
                })

            draft.title = title
            draft.content = content
            draft.post_type = post_type
            draft.event_id = event_id if event_id else None

            if action == 'publish':
                # 发布草稿
                post = draft.publish()
                return JsonResponse({
                    'status': 'success',
                    'message': '帖子发布成功',
                    'post_id': post.id
                })
            else:
                # 保存草稿
                draft.save()
                return JsonResponse({
                    'status': 'success',
                    'message': '草稿保存成功',
                    'draft_id': draft.id
                })

        except Exception as e:
            return JsonResponse({
                'status': 'error',
                'message': f'操作失败: {str(e)}'
            })

    # GET 请求显示编辑页面
    events = Event.objects.filter(status='published', start_time__gte=timezone.now())

    context = {
        'page_title': f'编辑草稿 - {draft.title}',
        'draft': draft,
        'events': events,
        'page_type': 'draft'
    }
    return render(request, 'community/edit_post.html', context)


@login_required
def delete_draft(request, draft_id):
    """删除草稿"""
    if request.method == 'POST':
        try:
            draft = get_object_or_404(PostDraft, id=draft_id, author=request.user)
            draft.delete()

            return JsonResponse({
                'status': 'success',
                'message': '草稿删除成功'
            })
        except Exception as e:
            return JsonResponse({
                'status': 'error',
                'message': f'删除失败: {str(e)}'
            })

    return JsonResponse({
        'status': 'error',
        'message': '无效的请求方法'
    })


@login_required
def restore_draft(request, draft_id):
    """恢复被举报的草稿为正式帖子"""
    if request.method == 'POST':
        try:
            draft = get_object_or_404(PostDraft, id=draft_id, author=request.user, status='reported')

            # 创建正式帖子
            post = CommunityPost.objects.create(
                title=draft.title,
                content=draft.content,
                author=draft.author,
                post_type=draft.post_type,
                event=draft.event,
                status='published'
            )

            # 创建用户动态
            UserActivity.objects.create(
                user=request.user,
                activity_type='post_created',
                target_post=post
            )

            # 删除草稿
            draft.delete()

            return JsonResponse({
                'status': 'success',
                'message': '帖子恢复成功',
                'post_id': post.id
            })
        except Exception as e:
            return JsonResponse({
                'status': 'error',
                'message': f'恢复失败: {str(e)}'
            })

    return JsonResponse({
        'status': 'error',
        'message': '无效的请求方法'
    })


@login_required
def report_post(request, post_id):
    """举报帖子 - 完善版"""
    if request.method == 'POST':
        try:
            post = get_object_or_404(CommunityPost, id=post_id, status='published')
            reason = request.POST.get('reason', '').strip()

            if not reason:
                return JsonResponse({
                    'status': 'error',
                    'message': '请填写举报原因'
                })

            # 定义违禁关键词列表
            banned_keywords = [
                '垃圾', '诈骗', '骗钱', '骗子', '虚假', '假活动',
                '色情', '淫秽', '黄色', '成人', '约炮',
                '暴力', '恐怖', '反动', '政治', '敏感',
                '广告', '推销', '营销', '微商', '传销',
                '赌博', '博彩', '六合彩', '赌球',
                '毒品', '吸毒', '违禁品',
                '攻击', '辱骂', '诽谤', '人身攻击'
            ]

            # 检查帖子内容是否包含违禁词
            post_content = (post.title + ' ' + post.content).lower()
            found_keywords = []

            for keyword in banned_keywords:
                if keyword in post_content:
                    found_keywords.append(keyword)

            # 更新举报计数
            post.report_count += 1
            post.last_reported_at = timezone.now()

            # 如果找到违禁词或者举报次数超过阈值，移动到草稿箱
            if found_keywords or post.report_count >= 3:  # 3次举报自动隐藏
                # 移动到草稿箱
                draft = post.move_to_draft(
                    report_reason=reason,
                    reported_by=request.user
                )

                return JsonResponse({
                    'status': 'success',
                    'message': f'举报成功！检测到违禁词: {", ".join(found_keywords)}，帖子已移至草稿箱',
                    'violation_found': True,
                    'keywords': found_keywords,
                    'moved_to_draft': True,
                    'draft_id': draft.id
                })
            else:
                post.save()
                return JsonResponse({
                    'status': 'success',
                    'message': '举报已提交，管理员会审核处理',
                    'violation_found': False,
                    'moved_to_draft': False
                })

        except Exception as e:
            return JsonResponse({
                'status': 'error',
                'message': f'举报失败: {str(e)}'
            })

    return JsonResponse({
        'status': 'error',
        'message': '无效的请求方法'
    })


@login_required
def edit_post(request, post_id):
    """编辑帖子"""
    post = get_object_or_404(CommunityPost, id=post_id, is_active=True)

    # 检查权限
    if post.author != request.user:
        return JsonResponse({
            'status': 'error',
            'message': '没有权限编辑此帖子'
        })

    if request.method == 'POST':
        try:
            title = request.POST.get('title')
            content = request.POST.get('content')
            post_type = request.POST.get('post_type', 'discussion')
            event_id = request.POST.get('event_id')

            if not title or not content:
                return JsonResponse({
                    'status': 'error',
                    'message': '标题和内容不能为空'
                })

            post.title = title
            post.content = content
            post.post_type = post_type
            post.event_id = event_id if event_id else None
            post.updated_at = timezone.now()
            post.save()

            return JsonResponse({
                'status': 'success',
                'message': '帖子更新成功',
                'post_id': post.id
            })
        except Exception as e:
            return JsonResponse({
                'status': 'error',
                'message': f'更新失败: {str(e)}'
            })

    # GET 请求 - 返回帖子数据用于编辑
    events = Event.objects.filter(status='published', start_time__gte=timezone.now())

    context = {
        'page_title': f'编辑帖子 - {post.title}',
        'post': post,
        'events': events,
    }
    return render(request, 'community/edit_post.html', context)


@login_required
def delete_post(request, post_id):
    """删除帖子"""
    if request.method == 'POST':
        try:
            post = get_object_or_404(CommunityPost, id=post_id, is_active=True)

            # 检查权限
            if post.author != request.user:
                return JsonResponse({
                    'status': 'error',
                    'message': '没有权限删除此帖子'
                })

            # 软删除，将 is_active 设为 False
            post.is_active = False
            post.save()

            return JsonResponse({
                'status': 'success',
                'message': '帖子删除成功',
                'redirect_url': '/location/community/posts/'
            })
        except Exception as e:
            return JsonResponse({
                'status': 'error',
                'message': f'删除失败: {str(e)}'
            })

    return JsonResponse({
        'status': 'error',
        'message': '无效的请求方法'
    })
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, get_object_or_404
from django.http import JsonResponse
from django.utils import timezone
from django.db.models import Sum
import json
from datetime import datetime, timedelta


# 添加积分相关视图
@login_required
def point_history(request):
    """积分明细页面"""
    from .models import PointTransaction

    transactions = PointTransaction.objects.filter(user=request.user).select_related(
        'related_event', 'related_post'
    )[:50]  # 最近50条记录

    # 计算积分统计
    today = timezone.now().date()
    today_points = PointTransaction.objects.filter(
        user=request.user,
        transaction_type='earn',
        created_at__date=today
    ).aggregate(total=Sum('points'))['total'] or 0

    month_start = today.replace(day=1)
    month_points = PointTransaction.objects.filter(
        user=request.user,
        transaction_type='earn',
        created_at__date__gte=month_start
    ).aggregate(total=Sum('points'))['total'] or 0

    point_summary = {
        'total_points': request.user.points,
        'total_earned': request.user.total_points_earned,
        'today_points': today_points,
        'month_points': month_points,
        'level': request.user.level,
        'experience': request.user.experience,
        'next_level_exp': (request.user.level) * 1000,
        'progress_percentage': min(100, (request.user.experience % 1000) / 10)
    }

    context = {
        'transactions': transactions,
        'point_summary': point_summary,
        'page_title': '积分明细'
    }

    return render(request, 'point_history.html', context)


@login_required
def point_rules(request):
    """积分规则页面"""
    from .models import PointRule
    rules = PointRule.objects.filter(is_active=True)
    return render(request, 'point_rules.html', {'rules': rules})


@login_required
def user_points_summary(request):
    """用户积分统计API"""
    from .models import PointTransaction

    today = timezone.now().date()
    today_points = PointTransaction.objects.filter(
        user=request.user,
        transaction_type='earn',
        created_at__date=today
    ).aggregate(total=Sum('points'))['total'] or 0

    month_start = today.replace(day=1)
    month_points = PointTransaction.objects.filter(
        user=request.user,
        transaction_type='earn',
        created_at__date__gte=month_start
    ).aggregate(total=Sum('points'))['total'] or 0

    summary = {
        'total_points': request.user.points,
        'total_earned': request.user.total_points_earned,
        'today_points': today_points,
        'month_points': month_points,
        'level': request.user.level,
        'experience': request.user.experience,
        'next_level_exp': (request.user.level) * 1000,
        'progress_percentage': min(100, (request.user.experience % 1000) / 10)
    }

    return JsonResponse(summary)


# 初始化积分规则的函数
def init_point_rules_if_needed():
    """如果需要，初始化积分规则"""
    from .models import PointRule

    if PointRule.objects.exists():
        return

    rules_data = [
        {
            'rule_type': 'event_create',
            'points': 50,
            'daily_limit': 3,
            'description': '创建并发布一个活动'
        },
        {
            'rule_type': 'event_join',
            'points': 20,
            'daily_limit': 5,
            'description': '成功报名参加一个活动'
        },
        {
            'rule_type': 'event_review',
            'points': 10,
            'daily_limit': 10,
            'description': '对参与的活动进行评价'
        },
        {
            'rule_type': 'post_create',
            'points': 15,
            'daily_limit': 5,
            'description': '在社区发布一个帖子'
        },
        {
            'rule_type': 'comment_create',
            'points': 5,
            'daily_limit': 20,
            'description': '在活动或帖子中发表评论'
        },
        {
            'rule_type': 'daily_login',
            'points': 5,
            'daily_limit': 1,
            'description': '每日登录奖励'
        },
        {
            'rule_type': 'profile_complete',
            'points': 30,
            'daily_limit': 1,
            'description': '完善个人资料'
        },
    ]

    for rule_data in rules_data:
        PointRule.objects.get_or_create(
            rule_type=rule_data['rule_type'],
            defaults=rule_data
        )

    print('Initialized point rules')


# 在积分规则视图中调用初始化
@login_required
def point_rules(request):
    """积分规则页面"""
    # 检查并初始化积分规则
    init_point_rules_if_needed()

    from .models import PointRule
    rules = PointRule.objects.filter(is_active=True)
    return render(request, 'point_rules.html', {'rules': rules})
# 积分商城

from .models import Reward, RewardRedemption
from django.db.models import Q, Sum


def reward_mall(request):
    """积分商城首页"""
    # 获取可用商品（激活且库存大于0）
    available_rewards = Reward.objects.filter(
        is_active=True,
        stock_quantity__gt=0
    ).order_by('-created_at')

    # 获取售罄商品
    sold_out_rewards = Reward.objects.filter(
        is_active=True,
        stock_quantity=0
    ).order_by('-created_at')

    context = {
        'page_title': '积分商城 - 本地有约',
        'available_rewards': available_rewards,
        'sold_out_rewards': sold_out_rewards,
        'user': request.user,
    }
    return render(request, 'rewards/reward_mall.html', context)


@login_required
def reward_detail(request, reward_id):
    """商品详情页"""
    reward = get_object_or_404(Reward, id=reward_id, is_active=True)

    # 检查用户是否可以兑换
    can_redeem = False
    redemption_message = ""

    if reward.stock_quantity > 0:
        if request.user.points >= reward.points_required:
            can_redeem = True
        else:
            redemption_message = f"积分不足，需要 {reward.points_required} 积分，您当前有 {request.user.points} 积分"
    else:
        redemption_message = "商品已售罄"

    context = {
        'page_title': f'{reward.name} - 积分商城',
        'reward': reward,
        'can_redeem': can_redeem,
        'redemption_message': redemption_message,
        'user_points': request.user.points,
    }
    return render(request, 'rewards/reward_detail.html', context)


@login_required
@require_POST
def redeem_reward(request, reward_id):
    """兑换商品"""
    try:
        reward = get_object_or_404(Reward, id=reward_id, is_active=True)
        user = request.user

        # 验证商品状态
        if reward.stock_quantity <= 0:
            return JsonResponse({
                'success': False,
                'message': '商品已售罄'
            })

        # 验证用户积分
        if user.points < reward.points_required:
            return JsonResponse({
                'success': False,
                'message': f'积分不足，需要 {reward.points_required} 积分，您当前有 {user.points} 积分'
            })

        # 创建兑换记录
        redemption = RewardRedemption.objects.create(
            user=user,
            reward=reward,
            points_used=reward.points_required,
            status='pending'
        )

        # 扣除用户积分
        success, message = user.spend_points(
            points=reward.points_required,
            source_type='reward_redemption',
            description=f'兑换商品: {reward.name}'
        )

        if not success:
            # 如果扣分失败，删除兑换记录
            redemption.delete()
            return JsonResponse({
                'success': False,
                'message': f'兑换失败: {message}'
            })

        # 更新商品库存
        reward.stock_quantity -= 1
        reward.save()

        return JsonResponse({
            'success': True,
            'message': '兑换成功！请等待处理',
            'redemption_id': redemption.id,
            'remaining_points': user.points
        })

    except Exception as e:
        return JsonResponse({
            'success': False,
            'message': f'兑换失败: {str(e)}'
        })


@login_required
def redemption_history(request):
    """我的兑换记录"""
    redemptions = RewardRedemption.objects.filter(
        user=request.user
    ).select_related('reward').order_by('-redemption_time')

    # 统计
    total_redemptions = redemptions.count()
    total_points_spent = redemptions.aggregate(
        total=Sum('points_used')
    )['total'] or 0

    context = {
        'page_title': '我的兑换记录 - 积分商城',
        'redemptions': redemptions,
        'total_redemptions': total_redemptions,
        'total_points_spent': total_points_spent,
        'user': request.user,
    }
    return render(request, 'rewards/redemption_history.html', context)


@login_required
def redemption_detail(request, redemption_id):
    """兑换记录详情"""
    redemption = get_object_or_404(
        RewardRedemption,
        id=redemption_id,
        user=request.user
    )

    context = {
        'page_title': f'兑换详情 - {redemption.reward.name}',
        'redemption': redemption,
    }
    return render(request, 'rewards/redemption_detail.html', context)
@login_required
def debug_event_points(request, event_id=None):
    """详细诊断活动积分问题"""
    from .models import Event, PointTransaction, PointRule

    if event_id:
        # 诊断特定活动
        event = get_object_or_404(Event, id=event_id)
        events = [event]
    else:
        # 诊断用户的所有活动
        events = Event.objects.filter(organizer=request.user).order_by('-created_at')[:10]

    results = []

    for event in events:
        # 检查活动基本信息
        event_info = {
            'id': event.id,
            'title': event.title,
            'status': event.status,
            'created_at': event.created_at,
            'updated_at': event.updated_at,
            'organizer': event.organizer.username
        }

        # 检查积分规则
        try:
            rule = PointRule.objects.get(rule_type='event_create', is_active=True)
            rule_info = {
                'exists': True,
                'points': rule.points,
                'daily_limit': rule.daily_limit,
                'is_active': rule.is_active
            }
        except PointRule.DoesNotExist:
            rule_info = {'exists': False}

        # 检查积分记录
        transactions = PointTransaction.objects.filter(
            user=event.organizer,
            source_type='event_create',
            related_event=event
        )

        transaction_info = {
            'count': transactions.count(),
            'transactions': list(transactions.values('id', 'points', 'description', 'created_at'))
        }

        # 检查今日积分获取情况
        today = timezone.now().date()
        today_earned = PointTransaction.objects.filter(
            user=event.organizer,
            source_type='event_create',
            transaction_type='earn',
            created_at__date=today
        ).count()

        # 组装结果
        result = {
            'event': event_info,
            'rule': rule_info,
            'transactions': transaction_info,
            'today_earned': today_earned,
            'user_points': event.organizer.points
        }

        results.append(result)

    return JsonResponse({'results': results})


@login_required
@require_POST
def force_award_event_points(request, event_id):
    """强制为活动奖励积分（用于修复）"""
    try:
        event = get_object_or_404(Event, id=event_id, organizer=request.user)

        # 检查是否已有积分记录
        existing = PointTransaction.objects.filter(
            user=request.user,
            source_type='event_create',
            related_event=event
        ).exists()

        if existing:
            return JsonResponse({
                'success': False,
                'message': '该活动已有积分记录'
            })

        # 强制奖励积分
        from .services import PointService
        points = PointService.get_points_for_rule('event_create')

        if points <= 0:
            return JsonResponse({
                'success': False,
                'message': f'积分规则返回0或负数: {points}'
            })

        # 直接创建积分记录
        transaction = PointTransaction.objects.create(
            user=request.user,
            transaction_type='earn',
            points=points,
            source_type='event_create',
            description=f'创建活动: {event.title} (强制修复)',
            related_event=event
        )

        # 更新用户积分
        request.user.points += points
        request.user.total_points_earned += points
        request.user.save()

        return JsonResponse({
            'success': True,
            'message': f'强制奖励 {points} 积分成功',
            'points_awarded': points,
            'new_balance': request.user.points
        })

    except Exception as e:
        return JsonResponse({
            'success': False,
            'message': f'强制奖励积分失败: {str(e)}'
        })

# 积分签到
@csrf_exempt
@require_http_methods(["POST"])
@login_required
def checkin_event(request):
    """活动签到API - 严格时间控制"""
    try:
        data = json.loads(request.body)
        event_id = data.get('event_id')

        if not event_id:
            return JsonResponse({
                'success': False,
                'message': '缺少活动ID'
            })

        event = get_object_or_404(Event, id=event_id)
        now = timezone.now()

        # 检查活动时间
        if now < event.start_time:
            return JsonResponse({
                'success': False,
                'message': f'活动尚未开始，开始时间：{event.start_time.strftime("%m月%d日 %H:%M")}'
            })

        if now > event.end_time:
            return JsonResponse({
                'success': False,
                'message': f'活动已结束，无法签到'
            })

        # 检查用户是否已报名
        is_registered = EventRegistration.objects.filter(
            event=event,
            user=request.user,
            status='registered'
        ).exists()

        if not is_registered:
            return JsonResponse({
                'success': False,
                'message': '只有报名用户才能签到'
            })

        # 检查是否已签到
        existing_checkin = Checkin.objects.filter(
            event=event,
            user=request.user
        ).exists()

        if existing_checkin:
            return JsonResponse({
                'success': False,
                'message': '您已经签到过了'
            })

        # 创建签到记录
        checkin = Checkin.objects.create(
            event=event,
            user=request.user
        )

        # 积分奖励逻辑
        points_earned = 0
        try:
            from .services import PointService
            success, point_message = PointService.handle_event_checkin(request.user, event)
            if success:
                point_transaction = PointTransaction.objects.filter(
                    user=request.user,
                    related_event=event,
                    source_type='event_checkin'
                ).first()
                if point_transaction:
                    points_earned = point_transaction.points
        except Exception as e:
            print(f"签到积分奖励失败: {str(e)}")

        return JsonResponse({
            'success': True,
            'message': '签到成功！' + (f' 获得 {points_earned} 积分！' if points_earned else ''),
            'checkin_time': checkin.created_at.isoformat(),
            'points_earned': points_earned
        })

    except Exception as e:
        print(f"签到异常: {str(e)}")
        return JsonResponse({
            'success': False,
            'message': f'签到失败: {str(e)}'
        }, status=500)


@login_required
def checkin_list(request, event_id):
    """签到列表 - 仅组织者可见"""
    try:
        event = get_object_or_404(Event, id=event_id)

        # 检查权限
        if event.organizer != request.user:
            return JsonResponse({
                'success': False,
                'message': '只有活动组织者才能查看签到列表'
            })

        # 修正：使用正确的字段名 created_at 而不是 checkin_time
        checkins = Checkin.objects.filter(event=event).select_related('user').order_by('-created_at')

        checkin_data = []
        for checkin in checkins:
            # 安全地获取头像URL
            avatar_url = '/static/images/default-avatar.jpg'
            try:
                if hasattr(checkin.user, 'avatar') and checkin.user.avatar:
                    avatar_url = checkin.user.avatar.url
            except:
                pass

            checkin_data.append({
                'user_id': checkin.user.id,
                'username': checkin.user.username,
                'checkin_time': checkin.created_at.strftime('%Y-%m-%d %H:%M'),  # 修正：使用 created_at
                'avatar_url': avatar_url
            })

        return JsonResponse({
            'success': True,
            'checkins': checkin_data,
            'total_count': len(checkin_data)
        })

    except Exception as e:
        print(f"签到列表错误: {str(e)}")
        import traceback
        print(traceback.format_exc())
        return JsonResponse({
            'success': False,
            'message': f'服务器错误: {str(e)}'
        })